package com.donleo.job.task;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ScheduledFuture;

/**
 * 动态添加、修改、删除定时任务
 *
 * @author liangd
 * @since 2021-03-03 18:39
 */
@RestController
public class DynamicTask {
    /**
     * （a）我们首先了一个类DynamicTask;
     * （b）定义了两个变量，threadPoolTaskScheduler和future 其中future是treadPoolTaskScheduler执行方法schedule的返回值，主要用于定时任务的停止。
     * （c）编写启动定时器的方法startCron()；
     * （d）编写停止方法stopCron(),这里编码的时候，需要注意下需要判断下future为null的时候，不然就很容易抛出NullPointerException；
     * （e）编写修改定时任务执行周期方法changeCron10（），这里的原理就是关闭之前的定时器，创新在创建一个新的定时器。
     *
     *
     * ThreadPoolTaskScheduler四个版本定时任务方法：
     * 1、schedule(Runnable task, Date stateTime)，在指定时间执行一次定时任务
     *
     * 2、schedule(Runnable task, Trigger trigger)，动态创建指定表达式cron的定时任务，
     *    threadPoolTaskScheduler.schedule(() -> {}, triggerContext -> newCronTrigger("").nextExecutionTime(triggerContext));
     *
     * 3、scheduleAtFixedRate，指定间隔时间执行一次任务，间隔时间为前一次执行开始到下一次任务开始时间
     *
     * 4、scheduleWithFixedDelay，指定间隔时间执行一次任务，间隔时间为前一次任务完成到下一次开始时间
     */
    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    private ScheduledFuture<?> future;

    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
        return new ThreadPoolTaskScheduler();
    }

    /**
     * 开始任务
     */
    @RequestMapping("/startCron")
    public String startCron() {
        //corn表达式
//        future = threadPoolTaskScheduler.schedule(new MyRunnable(), new CronTrigger("0/5 * * * * *"));
        long currentTimeMillis = System.currentTimeMillis();
        //表示5秒之后执行任务，而且只执行一次
        long spacingTime = 5 * 1000;
        DateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = formater.format(currentTimeMillis + spacingTime);
        Date startDate = null;
        try {
            startDate = formater.parse(format);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        assert startDate != null;
        System.out.println(new Date());
        //Date时间类,在这个时间段执行任务
        future = threadPoolTaskScheduler.schedule(new MyRunnable(), startDate);
        System.out.println("DynamicTask.startCron()");
        return "startCron";
    }

    /**
     * 结束任务
     */
    @RequestMapping("/stopCron")
    public String stopCron() {
        if (future != null) {
            future.cancel(true);
        }
        System.out.println("DynamicTask.stopCron()");
        return "stopCron";
    }

    /**
     * 开始新的任务
     */
    @RequestMapping("/changeCron10")
    public String startCron10() {

        stopCron();// 先停止，在开启.
        future = threadPoolTaskScheduler.schedule(new MyRunnable(), new CronTrigger("*/10 * * * * *"));
        System.out.println("DynamicTask.startCron10()");
        return "changeCron10";
    }

    /**
     * 执行线程
     */
    private class MyRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("DynamicTask.MyRunnable.run()，" + new Date());
        }
    }
}
